Python: pathlib.Path を使えない関数がある
結論
urllib.parse.quote() これはstr/bytesだけを想定している
open py35ではNG, 3.6ではOK
pathlibを使えるところは増えてきている
osモジュールなど
NGな例
isinstance(obj, str) はFalseなので、そのような処理があるところにPathオブジェクトを渡すとはまる
py36未満で、内部で open() を使ってる箇所でエラーになる
code:python
>> conn = sqlite3.connect(pathlib.Path(...))
...
TypeError: argument 1 must be str, not PosixPath`
sqlite3.connect
logging.FileHandler
open の例
code:py35(python)
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25)
Type "help", "copyright", "credits" or "license" for more information.
>> import pathlib
>> p = pathlib.Path('./test.txt')
>> with open(p, 'w') as f:
... f.write('hoge')
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: invalid file: PosixPath('test.txt')
code:Py36(python)
Python 3.6.6 (v3.6.6:4cf1f54eb7, Jun 26 2018, 19:50:54)
Type "help", "copyright", "credits" or "license" for more information.
>> import pathlib
>> p = pathlib.Path('./test.txt')
>> with open(p, 'w') as f:
... f.write('hoge')
...
4
------------
urllib.parse.quote の例
code:quote_path.py
Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04)
Type "help", "copyright", "credits" or "license" for more information.
>> from urllib.parse import quote
>> from pathlib import Path
>> p = Path('.')
>> p
PosixPath('.')
>> p / 'subdir' / '日本語.txt'
PosixPath('subdir/日本語.txt')
このパスをURLとして使いたい場合、日本語ファイル名のままだと困るのでquoteしたい。
pathlib.Pathはフィアルシステムのパスを表すので、そのままURLに使おうとしている
ファイルを格納したあるパスをURLにマッピングすることはよくある
code:quote_path.py
>> quote((p / 'subdir' / '日本語.txt'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/parse.py", line 775, in quote
return quote_from_bytes(string, safe)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/parse.py", line 800, in quote_from_bytes
raise TypeError("quote_from_bytes() expected bytes")
TypeError: quote_from_bytes() expected bytes
一見意味が分からないエラー。bytesを渡さないとだめなの?
code:quote_path.py
>> quote('foo')
'foo'
大丈夫。
Noneを渡すと同じ問題がおこる。
code:quote_path.py
>> quote(None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/parse.py", line 775, in quote
return quote_from_bytes(string, safe)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/urllib/parse.py", line 800, in quote_from_bytes
raise TypeError("quote_from_bytes() expected bytes")
TypeError: quote_from_bytes() expected bytes
strに変換してからquoteすれば期待した結果になる
code:quote_path.py
>> quote(str(p / 'subdir' / '日本語.txt'))
'subdir/%E6%97%A5%E6%9C%AC%E8%AA%9E.txt'
quote関数でstrをbytesに変換してquote_from_bytes()を呼んでいるが、そこでbytes以外はエラーとする処理があるのがこのエラーの原因。型を見てチェックしているので、 pathlib.Path ではエラーになる。